This notebook provides you with an example of how to create a stacked plot of oceanographic data variables in R. The specific data used in this example come from the Ocean Observatories Intiative’s suite of oceanographic data off of Newport, Oregon (Cabled Endurance Array), and were queried using the Data Explorer and exported into csv format.

Data used in this example were part of a project evaluating a period of April, 2018, and include the following environmental variables: sea water temperature (Degrees C), partial pressure of CO2 (uatm), Salinity (PSS), and dissolved O2 (umol/L). The final product in this example is a stacked set of line graphs that retain the scale specific to each dataset.

Loading Packages & Data

First you will load (after installing locally) the following packages:

library(tidyverse)
## -- Attaching packages --------------------------------------- tidyverse 1.3.1 --
## v ggplot2 3.3.5     v purrr   0.3.4
## v tibble  3.1.3     v dplyr   1.0.7
## v tidyr   1.1.3     v stringr 1.4.0
## v readr   2.0.0     v forcats 0.5.1
## -- Conflicts ------------------------------------------ tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
library(ggplot2)
library(scales)
## 
## Attaching package: 'scales'
## The following object is masked from 'package:purrr':
## 
##     discard
## The following object is masked from 'package:readr':
## 
##     col_factor
library(gridExtra)
## 
## Attaching package: 'gridExtra'
## The following object is masked from 'package:dplyr':
## 
##     combine
library(grid)
library(gtable)
library(lubridate)
## 
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
## 
##     date, intersect, setdiff, union

Next we will load in the data for each of the four variables (note: download all four csv files from and set working directory locally when on your own computer!). We will then need to use the as.POSIXct function to convert the date/time into a format that allows you to display along the x-axis.

  1. Start first with the temperature..
Temp <- read_csv("ooi-ce04osbp-lj01c-SeaWaterTemp580m_April2018.csv") %>%
  mutate(Date_Time = mdy_hm(Date_Time), 
         Date = mdy(Date))
## Rows: 40893 Columns: 4
## -- Column specification --------------------------------------------------------
## Delimiter: ","
## chr (3): Date, Time, Date_Time
## dbl (1): sea_water_temp_degC
## 
## i Use `spec()` to retrieve the full column specification for this data.
## i Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Check all is good
Temp
  1. Next we add in partial pressure of CO2:
PCO2 <- read_csv("ooi-ce04osbp-lj01c-PCO2_April2018.csv")%>%
  mutate(Date_Time = mdy_hm(Date_Time), 
         Date = mdy(Date))
## Rows: 669 Columns: 4
## -- Column specification --------------------------------------------------------
## Delimiter: ","
## chr (3): Date, Time, Date_Time
## dbl (1): pp_CO2
## 
## i Use `spec()` to retrieve the full column specification for this data.
## i Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Check all is good
PCO2
  1. And the salinity:
Salinity <- read_csv("ooi-ce04osbp-lj01c-Salinity580m_April2018.csv") %>%
  mutate(Date_Time = mdy_hm(Date_Time), 
         Date = mdy(Date))
## Rows: 40893 Columns: 4
## -- Column specification --------------------------------------------------------
## Delimiter: ","
## chr (3): Date, Time, Date_Time
## dbl (1): Salinity_0.001
## 
## i Use `spec()` to retrieve the full column specification for this data.
## i Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Check all is good
Salinity
  1. And finally the dissolved oxygen data:
DisO2 <- read_csv("ooi-ce04osbp-lj01c-DissolvedOxygen_April2018.csv")%>%
  mutate(Date_Time = mdy_hm(Date_Time), 
         Date = mdy(Date))
## Rows: 40893 Columns: 4
## -- Column specification --------------------------------------------------------
## Delimiter: ","
## chr (3): Date, Time, Date_Time
## dbl (1): DO
## 
## i Use `spec()` to retrieve the full column specification for this data.
## i Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Check all is good
DisO2

Plotting the Data

Below the four separate figures are created and then compiled NOTE: if you are keeping as separate then get rid of the axis title removals related to margin: margin(t = 0, r = 0, b = 0, l = 0, unit = “pt”)

NOTE: in the figures below, if you wanted to delete the x-axis data labels for as they almost line up for each of the figures (not perfectly because there are slightly different starting/ending points of data available), then you could un-comment the lines in the first three figures. This would result in you having just a single Date label along the x axis of the bottom figure.

We will create each of the line graph figures separately:

  1. Sea Surface Temperature
TempLine <- ggplot(Temp, aes(x = Date_Time, y = sea_water_temp_degC)) +
  geom_line(colour = "dark red", size = 1) +
  # scale_x_datetime(labels = date_format("%b %d")) +
  labs(x = "Date (UTC)", y = paste0("Sea Water Temp", "\n", "(Degrees C)")) +
  theme(text = element_text(size = 14)) +
  theme(axis.title.y = element_text(size = 12)) +
  theme(axis.title.x = element_blank(), 
        # axis.text.x = element_blank(), 
        axis.title.y = element_text(margin=margin(r=20)))

TempLine

  1. Partial pressure of CO2
PCO2Line <- ggplot(PCO2, aes(x = Date_Time, y = pp_CO2)) +
  geom_line(colour = "dark green", size = 1) +
  # scale_x_datetime(labels = date_format("%b %d")) +
  labs(x = "Date (UTC)", y = paste0("Partial Pressure", "\n", "CO2 (uatm)")) +
  theme(text = element_text(size = 14)) +
  theme(axis.title.y = element_text(size = 12)) +
  theme(axis.title.x = element_blank(), 
        # axis.text.x = element_blank(), 
        axis.title.y = element_text(margin=margin(r=20)))

PCO2Line

  1. Salinity
SalinityLine <- ggplot(Salinity, aes(x = Date_Time, y = Salinity_0.001)) +
  geom_line(colour = "purple", size = 1) +
  # scale_x_datetime(labels = date_format("%b %d")) +
  labs(x = "Date (UTC)", y = paste0("Salinity", "\n", "(PSS)")) +
  theme(text = element_text(size = 14)) +
  scale_y_continuous(labels = label_number(accuracy = 0.1)) +
  theme(axis.title.y = element_text(size = 12)) +
  theme(axis.title.x = element_blank(), 
        # axis.text.x = element_blank(), 
        axis.title.y = element_text(margin=margin(r=20)))

SalinityLine

  1. Dissolved Oxygen
DisO2Line <- ggplot(DisO2, aes(x = Date_Time, y = DO)) +
  geom_line(colour = "blue", size = 1) +
  # scale_x_datetime(labels = date_format("%b %d")) +
  labs(x = "Date (UTC)", y = paste0("Dissolved O2", "\n", "(umol/L)")) +
  theme(text = element_text(size = 14)) +
  theme(axis.title.y = element_text(size = 12)) +
  theme(axis.title.x = element_text(margin=margin(t=20)), 
        axis.title.y = element_text(margin=margin(r=20)))

DisO2Line

Stack the Plots

In this last step, we will compile all of the figures generated using the grid.arrange function. You’ll see the date is only displayed along the bottom, so if you wanted something different aesthetically, you could change that in the code for the figures above.

NOTE: there is a very slight offset in the values of this figure due to slightly different start time of data and labels, etc. There is a way to compensate for this using gtable, but that code is not included in this notebook.

AllOcean <- grid.arrange(TempLine, PCO2Line, SalinityLine, DisO2Line, ncol = 1, heights = c(1,1,1,1))

AllOcean
## TableGrob (4 x 1) "arrange": 4 grobs
##   z     cells    name           grob
## 1 1 (1-1,1-1) arrange gtable[layout]
## 2 2 (2-2,1-1) arrange gtable[layout]
## 3 3 (3-3,1-1) arrange gtable[layout]
## 4 4 (4-4,1-1) arrange gtable[layout]

And finally you might want to export this to a jpg or some other format:

ggsave(AllOcean, filename = "OOI_StackedOceanographicData.jpg", device = "jpeg", dpi = 300)
## Saving 7 x 5 in image
# if you want to specify the image height/width you can insert this after dpi: 
# width = 12, height = 8, units = "in"

Interactivity with Dygraphs

Dygraphs is an open source JavaScript charting library that allows you to plot interactive figures. In this last example we will first convert the dataframe into an xts type object, and then will create the interactive figure. You will need the zoo and xts as well as dygraphs and html tools

library(zoo)
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
library(xts)
## 
## Attaching package: 'xts'
## The following objects are masked from 'package:dplyr':
## 
##     first, last
library(dygraphs)
library(htmltools)
TempXTS <- Temp %>% read.zoo() %>% as.xts()
## Warning in zoo(rval3, ix): some methods for "zoo" objects do not work if the
## index entries in 'order.by' are not unique
PCO2XTS <- PCO2 %>% read.zoo() %>% as.xts()
## Warning in zoo(rval3, ix): some methods for "zoo" objects do not work if the
## index entries in 'order.by' are not unique
SalinityXTS <- Salinity %>% read.zoo() %>% as.xts()
## Warning in zoo(rval3, ix): some methods for "zoo" objects do not work if the
## index entries in 'order.by' are not unique
DisO2XTS <- DisO2 %>% read.zoo() %>% as.xts()
## Warning in zoo(rval3, ix): some methods for "zoo" objects do not work if the
## index entries in 'order.by' are not unique

Now we will combine all of these into a single object that will be an interactive chart. If you had all your data in a single dataframe then you would be able interact with the values concurrently, but since we have different variables with different units in separate tables, we can see scrolling values per figure.

The chart is interactive: you can mouse over to highlight individual values. You can click and drag to zoom. Double-clicking will zoom you back out. Shift-drag will pan. You can change the number and hit enter to adjust the averaging period.

There is a range selector at the bottom for you to select date range.

You could share figure using a plotly account/package (not shown here), or could view in html link provided in project files.

Finally, since we have four datasets here, the figures are viewed better if you select the option in the upper right hand corner of the figure (small symbol) that says “Show in New Window” to expand.

PlotOceanData <- list(
  dygraphs::dygraph(TempXTS, group="Date_Time", main="sea_water_temp_degC"),
  dygraphs::dygraph(PCO2XTS, group="Date_Time", main="pp_CO2"),
  dygraphs::dygraph(SalinityXTS, group="Date_Time", main="Salinity_0.001"),
  dygraphs::dygraph(DisO2XTS, group="Date_Time", main="DO")
  %>% dyRangeSelector()
)  # end list


# render the dygraphs objects using htmltools
htmltools::browsable(htmltools::tagList(PlotOceanData))

Wha-la! How much fun was that?!